﻿#include "Particle.h"
#include "Util.h"
#include <vector>
#include <cmath>

using namespace std;

Particle::Particle()
{

}

Particle::Particle(	ParticleSwarm* swarm,vector<double> position, vector<double> velocity)
{	
	this->Swarm = swarm;
	pPosition=position;
	pVelocity=velocity;
}

Particle::~Particle()
{
	
}

void Particle::CalculateCost()
{
	//Cost = costFunction->psoFunction_For_Single_Particle(Position);
}

void Particle::update_Data(double pCostValue,bool forceUpdate) // get Cost & update pBest
{
	pCost = pCostValue;
	if(pCost < pBestCost || forceUpdate)
	{
		pBestCost = pCost;
		pBestPosition = pPosition;
	}
}

void Particle::UpdatePBest()
{
	if(pCost < pBestCost)
	{
		pBestCost = pCost;
		pBestPosition = pPosition;
	}
}

void Particle::UpdateVelocityAndPosition(vector<double> bestPositionOfSwarm)
{
    ///	Set the maximum velocity
	double xmax = abs(Max(pPosition));
	if ( abs(Min(pPosition)) > abs(Max(pPosition)) )
	{
		xmax = abs(Min(pPosition));
	}
	double vmax = Swarm->PercentMaximumVelocityOfSearchSpace * xmax;


	for (int i = 0; i < pVelocity.size(); i++)
	{
		///	Speed ​​calculation parameters
		double c1 = Swarm->TendencyToOwnBest;
		double r1 = _rnd.NextDouble();
		double c2 = Swarm->TendencyToGlobalBest;
		double r2 = _rnd.NextDouble();
		double w = Swarm->Momentum;

		/// Calculate the new rate
		double newVelocity = w * ( pVelocity[i] +
				c1 * r1 * (pBestPosition[i] - pPosition[i]) +
				c2 * r2 * (bestPositionOfSwarm[i] - pPosition[i]));

/*		///	Does not exceed the speed limit vmax
		if (newVelocity > vmax)
		{
			newVelocity = vmax;
		}
		if (newVelocity < -vmax)
		{
			newVelocity = -vmax;
		}
*/
		/// Update the new speed and position
		pVelocity[i] = newVelocity;
		pPosition[i] += pVelocity[i];
		if (pPosition[i] > Swarm->MaxRange[i])
			pPosition[i] = Swarm->MaxRange[i];
		if (pPosition[i] < Swarm->MinRange[i])
			pPosition[i] = Swarm->MinRange[i];
	}
}


//double& Particle::operator [](int i)
//{
//	return pPosition.at(i);
//}

double Particle::Max(vector<double> position)
{	
	vector<double>::iterator iter = position.begin();
	double max = *iter;
	for ( ; iter != position.end() ; ++iter)
	{
		if (*iter > max)
		{
			max = *iter;
		}
	}
	return max;
}


double Particle::Min(vector<double> position)
{
	vector<double>::iterator iter = position.begin();
	double min = *iter;
	for ( ; iter != position.end() ; ++iter)
	{
		if (*iter < min)
		{
			min = *iter;
		}
	}
	return min;
}